package com.rpframework.module.common.springmvc;

import com.rpframework.module.common.bottom.entity.enums.RequestType;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.condition.*;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 修改SpringMvc的URL映射为方法驼峰命名映射
 * 比如
 * 方法名:getUserInfo
 * 自动映射：/get/user/info
 */
public class AutoRequestMappingHandlerMapping extends RequestMappingHandlerMapping {

    private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();

    private final List<String> fileExtensions = new ArrayList<>();

    public AutoRequestMappingHandlerMapping() {
        this(null);
    }

    public AutoRequestMappingHandlerMapping(String controllerFix) {
        if (StringUtils.isBlank(controllerFix)) {
            controllerFix = "Controller";
        }
        RequestType.controllerFix = controllerFix;
        RequestType.requestMappingHandler = this;
    }

    @Override
    protected RequestMappingInfo getMappingForMethod(Method method,
                                                     Class<?> handlerType) {
        RequestMappingInfo info = null;
        RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);
        if (methodAnnotation != null) {
            RequestCondition<?> methodCondition = getCustomMethodCondition(method);
            info = createRequestMappingInfo(methodAnnotation, methodCondition, method, null);
            RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
            if (typeAnnotation != null) {
                RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);
                info = createRequestMappingInfo(typeAnnotation, typeCondition, null, handlerType).combine(info);
            }
        }
        return info;
    }

    private RequestMappingInfo createRequestMappingInfo(RequestMapping annotation, RequestCondition<?> customCondition, Method method,
                                                        Class<?> handlerType) {
        String[] patterns;
        if (method != null) {
            patterns = RequestType.parseUri(method);
        } else {
            patterns = RequestType.parseUri(handlerType);
        }
        return new RequestMappingInfo(
                new PatternsRequestCondition(patterns, getUrlPathHelper(), getPathMatcher(),
                        true, true, this.fileExtensions),
                new RequestMethodsRequestCondition(annotation.method()),
                new ParamsRequestCondition(annotation.params()),
                new HeadersRequestCondition(annotation.headers()),
                new ConsumesRequestCondition(annotation.consumes(), annotation.headers()),
                new ProducesRequestCondition(annotation.produces(), annotation.headers(), this.contentNegotiationManager),
                customCondition);

    }


}


